/*
 * @Author: xiaosihan
 * @Date: 2024-10-01 13:28:45
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2024-10-01 21:36:23
 */

import {
  Camera,
  DoubleSide,
  MeshBasicMaterial,
  Plane,
  PlaneGeometry,
} from "three";
import { TransformControls } from "three/examples/jsm/controls/TransformControls";
import { Group } from "three/src/objects/Group";
import { Mesh } from "three/src/objects/Mesh";

// 裁剪面模型
export default class ClipPlaneMesh extends Group {
  constructor(camera: Camera, domElement: HTMLElement) {
    super();
    this.controls = new TransformControls(camera, domElement);
    this.controls.addEventListener("change", () => {
      const sign = this.profileSide === "front" ? -1 : 1;
      const { x, y, z } = this.planeMesh.position;
      switch (this.direction) {
        case "x":
          this.plane.constant = x * sign;
          break;
        case "y":
          this.plane.constant = y * sign;
          break;
        case "z":
          this.plane.constant = z * sign;
          break;

        default:
          break;
      }
    });
    this.add(this.controls);
    this.controls.attach(this.planeMesh);
  }

  controls!: TransformControls;

  plane = new Plane();

  planeMesh = (() => {
    const palneGeo = new PlaneGeometry(1, 1, 1, 1);
    const planeMat = new MeshBasicMaterial({
      color: "#5503FA",
      side: DoubleSide,
      transparent: true,
      opacity: 0.3,
    });

    const planeMesh = new Mesh(palneGeo, planeMat);
    planeMesh.renderOrder = 10;
    this.add(planeMesh);
    return planeMesh;
  })();
  size = 1;
  profileSide = "front" as "front" | "back";
  direction = "x" as "x" | "y" | "z";
  //设置裁剪模型的大小
  setSize(width: number, height: number, deth: number) {
    this.size = Math.max(width, height, deth);
    this.planeMesh.scale.set(this.size, this.size, this.size);
  }

  set({
    visible,
    direction,
    profileSide,
  }: {
    visible: boolean;
    direction: "x" | "y" | "z";
    profileSide: "front" | "back";
  }) {
    if (this.visible !== visible || this.direction !== direction) {
      this.plane.constant = 0;
      this.planeMesh.position.set(0, 0, 0);
    }
    this.visible = visible;
    this.direction = direction;
    this.controls.showX = direction === "x";
    this.controls.showY = direction === "y";
    this.controls.showZ = direction === "z";
    this.profileSide = profileSide;
    const sign = profileSide === "front" ? 1 : -1;
    const palneGeo = new PlaneGeometry(1, 1, 1, 1);
    const { x, y, z } = this.planeMesh.position;
    switch (direction) {
      case "x":
        palneGeo.rotateY(Math.PI / 2);
        this.plane.normal.set(sign, 0, 0);
        this.plane.constant = x * sign * -1;
        break;
      case "y":
        palneGeo.rotateX(Math.PI / 2);
        this.plane.normal.set(0, sign, 0);
        this.plane.constant = y * sign * -1;
        break;
      case "z":
        this.plane.normal.set(0, 0, sign);
        this.plane.constant = z * sign * -1;
        break;

      default:
        break;
    }
    this.planeMesh.geometry = palneGeo;
  }

}
